package cn.javacart.jopencart.controller.catalog.product;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringEscapeUtils;

import php.runtime.memory.StringMemory;
import php.runtime.memory.support.MemoryUtils;
import cn.javacart.jfinal.php.render.PhpRender;
import cn.javacart.jopencart.controller.catalog.common.CommonColumnLeftModule;
import cn.javacart.jopencart.controller.catalog.common.CommonColumnRightModule;
import cn.javacart.jopencart.controller.catalog.common.CommonContentBottomModule;
import cn.javacart.jopencart.controller.catalog.common.CommonContentTopModule;
import cn.javacart.jopencart.controller.catalog.common.CommonFooterModule;
import cn.javacart.jopencart.controller.catalog.common.CommonHeaderModule;
import cn.javacart.jopencart.engine.JOpencartController;
import cn.javacart.jopencart.kit.ImageKit;
import cn.javacart.jopencart.kit.SetKit;
import cn.javacart.jopencart.kit.StrTool;
import cn.javacart.jopencart.library.PaginationService;
import cn.javacart.jopencart.model.Category;
import cn.javacart.jopencart.model.Product;
import cn.javacart.jopencart.service.catalog.catalog.CatalogCategoryService;
import cn.javacart.jopencart.service.catalog.catalog.CatalogProductService;
import cn.javacart.jopencart.util.ChainMap;

import com.jfinal.kit.StrKit;

/**
 * 商品目录界面
 * @author farmer
 *
 */
public class ProductCategoryController extends JOpencartController{

	/**
	 * 商品目录界面
	 */
	public void index(){
		language.load("/catalog/language/{0}/product/category.php");
		//导航
		List<Map<String, Object>> breadcrumbs = new ArrayList<Map<String,Object>>();
		breadcrumbs.add(ChainMap.createMap().put("text", language.getStr("text_home")).put("href", url.linkStr("common/home", null)).toMap());
		//如果path存在
		Integer categoryId  = null;
		if(SetKit.isset(getPara("path"))){
			StringBuilder urlBuilder = new StringBuilder();
			if(StrKit.notBlank(getPara("filter"))){
				urlBuilder.append("&filter=").append(getPara("filter"));
			}
			if(StrKit.notBlank(getPara("sort"))){
				urlBuilder.append("&sort=").append(getPara("sort"));
			}
			if(StrKit.notBlank(getPara("order"))){
				urlBuilder.append("&order=").append(getPara("order"));
			}
			if(StrKit.notBlank(getPara("limit"))){
				urlBuilder.append("&limit=").append(getPara("limit"));
			}
			String path = null;
			List<String> parts = new ArrayList<String>(Arrays.asList(getPara("path").split("_")));
			int size = parts.size();
			categoryId = Integer.parseInt(parts.get(size-1));
			parts.remove(size-1);
			for (String pathId : parts) {
				if(path == null){
					path = pathId;
				} else {
					path =path + "_" + pathId;
				}
				Category categoryInfo = CatalogCategoryService.ME.getCategory(Integer.parseInt(pathId));
				if(categoryInfo != null){
					breadcrumbs.add(ChainMap.createMap().put("text", categoryInfo.get("name")).put("href", url.linkStr("product/category", "path="+path)).toMap());
				}
			}
		}else{
			categoryId = 0 ;
		}
		Category categoryInfo = CatalogCategoryService.ME.getCategory(categoryId);
		if(categoryInfo != null){
			document.setTitle(categoryInfo.getStr("meta_title"));
			document.setDescription(categoryInfo.getStr("meta_description"));
			document.setKeywords(categoryInfo.getStr("meta_keyword"));
			dataMap.put("heading_title", MemoryUtils.valueOf(categoryInfo.getStr("name")));
			dataMap.put("text_refine",language.get("text_refine"));
			dataMap.put("text_empty",language.get("text_empty"));
			dataMap.put("text_quantity",language.get("text_quantity"));
			dataMap.put("text_manufacturer",language.get("text_manufacturer"));
			dataMap.put("text_model",language.get("text_model"));
			dataMap.put("text_price",language.get("text_price"));
			dataMap.put("text_tax",language.get("text_tax"));
			dataMap.put("text_points",language.get("text_points"));
			dataMap.put("text_compare", MemoryUtils.valueOf(String.format(language.getStr("text_compare"), getSessionAttr("compare") != null?  ((List<?>)getSessionAttr("compare")).size() :0)));
			dataMap.put("text_sort",language.get("text_sort"));
			dataMap.put("text_limit",language.get("text_limit"));
			dataMap.put("button_cart",language.get("button_cart"));
			dataMap.put("button_wishlist",language.get("button_wishlist"));
			dataMap.put("button_compare",language.get("button_compare"));
			dataMap.put("button_continue",language.get("button_continue"));
			dataMap.put("button_list",language.get("button_list"));
			dataMap.put("button_grid",language.get("button_grid"));
			breadcrumbs.add(ChainMap.createMap()
					.put("text", categoryInfo.get("name"))
					.put("href", url.linkStr("product/category", "path="+getPara("path")))
					.toMap());
			String image = categoryInfo.getStr("image");
			if (StrKit.notBlank(image)) {
				dataMap.put("thumb", MemoryUtils.valueOf(ImageKit.resize(image, config.get(configTheme + "_image_thumb_width"), config.get(configTheme+"_image_thumb_height"))));
			} else {
				dataMap.put("thumb",new StringMemory(""));
			}
			dataMap.put("description", MemoryUtils.valueOf(StringEscapeUtils.unescapeHtml4(categoryInfo.getStr("description"))));
			dataMap.put("compare", url.link("product/compare", null));
			
			StringBuilder urlBuilder = new StringBuilder();
			if(StrKit.notBlank(getPara("filter"))){
				urlBuilder.append("&filter=").append(getPara("filter"));
			}
			if(StrKit.notBlank(getPara("sort"))){
				urlBuilder.append("&sort=").append(getPara("sort"));
			}
			if(StrKit.notBlank(getPara("order"))){
				urlBuilder.append("&order=").append(getPara("order"));
			}
			if(StrKit.notBlank(getPara("limit"))){
				urlBuilder.append("&limit=").append(getPara("limit"));
			}
			
			List<Map<String, Object>> categories = new ArrayList<Map<String,Object>>();
			for (Category category : CatalogCategoryService.ME.getCategories(categoryId)) {
				categories.add(
						ChainMap.createMap()
						.put("name", category.getStr("name")  + (SetKit.isset(config.getInt("config_product_count")) ?  "(" + 
									CatalogProductService.ME.getTotalProducts(
											ChainMap.createMap().put("filter_category_id", 
													category.getInt("category_id")).put("filter_sub_category", true).toMap())
									+")" : ""))
						.put("href", url.linkStr("product/category", "path="+getPara("path")+"_"+category.getInt("category_id")+urlBuilder.toString()))
						.toMap());
			}
			
			List<Map<String, Object>> products = new ArrayList<Map<String,Object>>();
			Map<String, Object> filterData = new HashMap<String, Object>();
			int limit = getParaToInt("limit",config.getInt(configTheme+"_product_limit"));
			filterData.put("filter", getPara("filter",""));	//筛选条件
			filterData.put("sort", getPara("sort","p.sort_order"));
			filterData.put("order", getPara("order","ASC"));
			Integer page = getParaToInt("page",1);
			filterData.put("page", page);
			filterData.put("start", (page - 1 ) * limit);
			filterData.put("limit", limit);
			filterData.put("filter_category_id", categoryId);
			Long total = CatalogProductService.ME.getTotalProducts(filterData);
			for (Map.Entry<Integer, Product> entry: CatalogProductService.ME.getProducts(filterData).entrySet()) {
				Product product = entry.getValue();
				if(SetKit.isset(product.getStr("image"))){
					image = ImageKit.resize(product.getStr("image"), config.get(configTheme+"_image_product_width") , 
							config.get(configTheme+"_image_product_height"));
				}else{
					image = ImageKit.resize("image/placeholder.png", 
							config.get(configTheme+"_image_product_width") , 
							config.get(configTheme+"_image_product_height"));
				}
				BigDecimal price = product.getBigDecimal("price");
				String priceValue = null;
				if(customer.isLogged() || config.isset("config_customer_price")){
					priceValue = currency.format(tax.calculate(price, product.getInt("tax_class_id"), (String)config.get("config_tax")), (String)getSessionAttr("currency"), null);
				}
				BigDecimal special = product.getBigDecimal("special");
				String specialValue = null;
				if(special != null){
					specialValue = currency.format(tax.calculate(special, product.getInt("tax_class_id"), (String)config.get("config_tax")), (String)getSessionAttr("currency"), null);
				}
				String taxValue = null;
				if(config.isset("config_tax")){
					taxValue = currency.format(special == null ?price : special, (String)getSessionAttr("currency"), null);
				}
				long rating = 0;
				if(config.isset("config_review_status")){
					rating = product.getLong("rating");
				}
				products.add(
						ChainMap.createMap()
						.put("product_id", product.get("product_id"))
						.put("thumb", image)
						.put("name", product.get("name"))
						.put("description", StrTool.subStrClearTag(StringEscapeUtils.unescapeHtml4(product.getStr("description")), 0, 100))
						.put("price", priceValue)
						.put("special", specialValue)
						.put("tax", taxValue)
						.put("minimum", product.getInt("minimum") > 0 ? product.getInt("minimum") :1)
						.put("rating", rating)
						.put("href", url.linkStr("product/product", "product_id="+product.getInt("product_id")))
						.toMap()
						);	
			}
			
			List<Map<String, Object>> sorts = new ArrayList<Map<String,Object>>();
			urlBuilder = new StringBuilder();
			if(StrKit.notBlank(getPara("filter"))){
				urlBuilder.append("&filter=").append(getPara("filter"));
			}
			if(StrKit.notBlank(getPara("limit"))){
				urlBuilder.append("&limit=").append(getPara("limit"));
			}
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_default"))
					.put("value", "p.sort_order-ASC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=p.sort_order&order=ASC" + urlBuilder.toString())).toMap());
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_name_asc"))
					.put("value", "pd.name-ASC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=pd.name&order=ASC" + urlBuilder.toString())).toMap());
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_price_asc"))
					.put("value", "p.price-ASC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=p.price&order=ASC" + urlBuilder.toString())).toMap());
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_price_desc"))
					.put("value", "p.price-DESC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=p.price&order=DESC" + urlBuilder.toString())).toMap());
			if(config.isset("config_review_status")){
				sorts.add(ChainMap.createMap()
						.put("text", language.getStr("text_rating_desc"))
						.put("value", "rating-DESC")
						.put("href", url.linkStr("product/category", "path="+getPara("path","") 
								+ "&sort=rating&order=DESC" + urlBuilder.toString())).toMap());
				sorts.add(ChainMap.createMap()
						.put("text", language.getStr("text_rating_asc"))
						.put("value", "rating-ASC")
						.put("href", url.linkStr("product/category", "path="+getPara("path","") 
								+ "&sort=rating&order=ASC" + urlBuilder.toString())).toMap());
			}
			
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_model_asc"))
					.put("value", "p.model-ASC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=p.model&order=ASC" + urlBuilder.toString())).toMap());
			sorts.add(ChainMap.createMap()
					.put("text", language.getStr("text_model_desc"))
					.put("value", "p.model-DESC")
					.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ "&sort=p.model&order=DESC" + urlBuilder.toString())).toMap());
			
			
			urlBuilder = new StringBuilder();
			if(StrKit.notBlank(getPara("filter"))){
				urlBuilder.append("&filter=").append(getPara("filter"));
			}
			if(StrKit.notBlank(getPara("sort"))){
				urlBuilder.append("&sort=").append(getPara("sort"));
			}
			if(StrKit.notBlank(getPara("order"))){
				urlBuilder.append("&order=").append(getPara("order"));
			}
			List<Integer> pageSizes = new ArrayList<Integer>(Arrays.asList(25, 50, 75, 100));
			if(!pageSizes.contains(config.getInt(configTheme+"_product_limit"))){				
				pageSizes.add(config.getInt(configTheme+"_product_limit"));
			}
			Collections.sort(pageSizes, new Comparator<Integer>() {
				@Override
				public int compare(Integer o1, Integer o2) {
					return o1 - o2;
				}
			});
			List<Map<String, Object>> limits = new ArrayList<Map<String,Object>>();
			for (Integer size : pageSizes) {
				limits.add(ChainMap.createMap()
						.put("text", size)
						.put("value", size)
						.put("href", url.linkStr("product/category", "path="+getPara("path","") 
							+ urlBuilder.toString() + "&limit="+size))
						.toMap());
				
			}
			if(StrKit.notBlank(getPara("limit"))){
				urlBuilder.append("&limit=").append(getPara("limit"));
			}
			PaginationService pagination = new PaginationService();
			pagination.total = total;
			pagination.page = page;
			pagination.limit = limit;
			pagination.url = url.linkStr("product/category", "path=" + getPara("path") + urlBuilder.toString() + "&page={page}");
			
			dataMap.put("pagination", MemoryUtils.valueOf(pagination.render()));
			dataMap.put("results", MemoryUtils.valueOf(String.format(language.getStr("text_pagination"), SetKit.isset(total) ? ((page-1)*limit ) +1 :0 ,  (((page-1)*limit ) > (total - limit)) ? total : (((page-1)*limit ) + limit) , total , (int)Math.ceil((double) total / (double) limit)  ) ));
			dataMap.put("limitss", MemoryUtils.valueOf(limits));
			dataMap.put("sort", MemoryUtils.valueOf(getPara("sort","p.sort_order")));
			dataMap.put("order", MemoryUtils.valueOf(getPara("order","ASC")));
			dataMap.put("limit", MemoryUtils.valueOf(getParaToInt("limit",config.getInt(configTheme+"_product_limit"))));
			dataMap.put("categories", MemoryUtils.valueOf(categories));	//分类
			dataMap.put("products", MemoryUtils.valueOf(products));	//商品
			dataMap.put("sorts", MemoryUtils.valueOf(sorts));
			dataMap.put("breadcrumbs", MemoryUtils.valueOf(breadcrumbs));	//导航
			dataMap.put("column_left", MemoryUtils.valueOf(load.module(new CommonColumnLeftModule(this))));
			dataMap.put("column_right", MemoryUtils.valueOf(load.module(new CommonColumnRightModule(this))));
			dataMap.put("content_top", MemoryUtils.valueOf(load.module(new CommonContentTopModule(this))));
			dataMap.put("content_bottom", MemoryUtils.valueOf(load.module(new CommonContentBottomModule(this))));
			dataMap.put("footer", MemoryUtils.valueOf(load.module(new CommonFooterModule(this))));
			dataMap.put("header", MemoryUtils.valueOf(load.module(new CommonHeaderModule(this))));
			render(new PhpRender("/catalog/view/theme/default/template/product/category.tpl", dataMap));
		
		}else{
			//分类404
			StringBuilder urlBuilder = new StringBuilder();
			if(StrKit.notBlank(getPara("path"))){
				urlBuilder.append("&path=").append(getPara("path"));
			}
			if(StrKit.notBlank(getPara("filter"))){
				urlBuilder.append("&filter=").append(getPara("filter"));
			}
			if(StrKit.notBlank(getPara("sort"))){
				urlBuilder.append("&sort=").append(getPara("sort"));
			}
			if(StrKit.notBlank(getPara("order"))){
				urlBuilder.append("&order=").append(getPara("order"));
			}
			if(StrKit.notBlank(getPara("page"))){
				urlBuilder.append("&page=").append(getPara("page"));
			}
			if(StrKit.notBlank(getPara("limit"))){
				urlBuilder.append("&limit=").append(getPara("limit"));
			}
			breadcrumbs.add(ChainMap.createMap()
					.put("text", language.getStr("text_error"))
					.put("href", url.linkStr("product/category",urlBuilder.toString()))
					.toMap());
			
			document.setTitle(language.getStr("text_error"));
			dataMap.put("heading_title",language.get("text_error"));
			dataMap.put("text_error",language.get("text_error"));
			dataMap.put("button_continue",language.get("button_continue"));
			dataMap.put("continue",url.link("common/home", null));
			
			dataMap.put("breadcrumbs", MemoryUtils.valueOf(breadcrumbs));	//导航
			dataMap.put("column_left", MemoryUtils.valueOf(load.module(new CommonColumnLeftModule(this))));
			dataMap.put("column_right", MemoryUtils.valueOf(load.module(new CommonColumnRightModule(this))));
			dataMap.put("content_top", MemoryUtils.valueOf(load.module(new CommonContentTopModule(this))));
			dataMap.put("content_bottom", MemoryUtils.valueOf(load.module(new CommonContentBottomModule(this))));
			dataMap.put("footer", MemoryUtils.valueOf(load.module(new CommonFooterModule(this))));
			dataMap.put("header", MemoryUtils.valueOf(load.module(new CommonHeaderModule(this))));
			getResponse().setStatus(404);
			render(new PhpRender("/catalog/view/theme/default/template/error/not_found.tpl", dataMap));
		}
	}
	
}
